package com.qing.demo.netty.server;

import com.alibaba.fastjson.JSON;
import com.qing.demo.netty.domain.ClientMsgProtocol;
import com.qing.demo.netty.util.ChannelHandler;
import com.qing.demo.netty.util.MsgUtil;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.http.*;
import io.netty.handler.codec.http.websocketx.*;
import io.netty.util.CharsetUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;




/**
 * @author caozhipeng
 * @date 2025/7/25
 */
public class MyServerHandler extends ChannelInboundHandlerAdapter {

    private Logger logger= LoggerFactory.getLogger(MyServerHandler.class);


    private WebSocketServerHandshaker handshaker;

//   当客户端主动链接后，这个通道就是活跃的，可以发送数据给客户端
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
//       当有客户端链接后，添加到ChannelGroup通信组
        SocketChannel socketChannel=(SocketChannel)ctx.channel();
        System.out.println("链接报告开始");
        System.out.println("链接报告信息：有一个客户端链接到本地服务器");
        System.out.println("链接报告IP:"+ socketChannel.localAddress().getHostString());
        System.out.println("链接报告端口:"+ socketChannel.localAddress().getPort());
        System.out.println("链接报告结束");

        ChannelHandler.channelGroup.add(ctx.channel());
    }

    /**
     * 当客户端主动断开服务器连接后，这个通道就是不活跃的，不可以传递数据
     * @param ctx
     * @throws Exception
     */
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        System.out.println(ctx.channel().id()+" 客户端断开链接");
        ChannelHandler.channelGroup.remove(ctx.channel());
    }

    // 异常处理
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        ctx.close();
        System.out.println("异常信息："+cause.getMessage());
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
       if(msg instanceof FullHttpRequest){
           FullHttpRequest httpRequest= (FullHttpRequest) msg;
           if(!httpRequest.decoderResult().isSuccess()){
               DefaultFullHttpResponse httpResponse=new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.BAD_REQUEST);
//               返回应答给客户端
               if(httpResponse.status().code()!=200){
                   ByteBuf buf=Unpooled.copiedBuffer(httpResponse.status().toString(), CharsetUtil.UTF_8);
                   httpResponse.content().writeBytes(buf);
                   buf.release();
               }
//               如果是非Keep-Alive，关闭连接
               ChannelFuture future = ctx.channel().writeAndFlush(httpResponse);
               if(httpResponse.status().code()!=200){
                   future.addListener(ChannelFutureListener.CLOSE);
               }
           }

           WebSocketServerHandshakerFactory wsFactory = new WebSocketServerHandshakerFactory(
                   "ws:/"+ctx.channel()+"/websocket", null, false);
           handshaker = wsFactory.newHandshaker(httpRequest);
           if(null==handshaker){
               WebSocketServerHandshakerFactory.sendUnsupportedVersionResponse(ctx.channel());
           }else{
               handshaker.handshake(ctx.channel(), httpRequest);
           }
           return;
       }

       if(msg instanceof WebSocketFrame){
           WebSocketFrame frame= (WebSocketFrame) msg;
//           关闭请求
           if(frame instanceof CloseWebSocketFrame){
               handshaker.close(ctx.channel(), (CloseWebSocketFrame) frame.retain());
               return;
           }
//           ping 请求
           if(frame instanceof PingWebSocketFrame){
               ctx.channel().write(new PongWebSocketFrame(frame.content()).retain());
               return;
           }

          if(!(frame instanceof TextWebSocketFrame)){
              throw  new RuntimeException("仅支持文本格式");
          }
          String request=((TextWebSocketFrame) frame).text();
          logger.info("服务端收到消息：{}",request);

           ClientMsgProtocol clientMsgProtocol= JSON.parseObject(request, ClientMsgProtocol.class);
           if(1==clientMsgProtocol.getType()){
               // 1 发送消息
               ctx.channel().writeAndFlush(MsgUtil.buildMsgOwner(ctx.channel().id().toString()));
               return;
           }
//           群发消息
           if(2==clientMsgProtocol.getType()){
               TextWebSocketFrame textWebSocketFram=MsgUtil.buildMsgAll(ctx.channel().id().toString(),clientMsgProtocol.getMsgInfo());
               ChannelHandler.channelGroup.writeAndFlush(textWebSocketFram);
           }
       }


    }

}
